package App.Model;

import App.Public.Lib.CopyUtil;
import App.Public.Lib.PingYingUtil;
import App.Public.Lib.SearchUtil;

import java.io.*;
import java.util.*;

public class UserData implements Serializable {
    /**
     * 用户名
     */
    private String username;
    /**
     * 根据组名来存储分组信息
     */
    private HashMap<String, Contact_Group> groupData = new HashMap<>();
    /**
     * 根据联系人名字存储所有联系人的信息
     */
    private HashMap<String, ArrayList<Contact_Message>> personBase = new HashMap<>();

    public UserData() {
    }

    public UserData(String username) {
        this.username = username;
//        try {
//            this.addGroup("未分组");
//        } catch (Exception e) {}
    }

    public UserData(String username, HashMap<String, Contact_Group> data, HashMap<String, ArrayList<Contact_Message>> basedata) {
        this.username = username;
        this.groupData = data;
        this.personBase = basedata;

//        try {
//            this.addGroup("未分组");
//        } catch (Exception e) {}
    }

    /**
     * 添加联系人
     *
     * @param person 联系人对象
     * @return 添加成功会返回true
     * @throws Exception 如果联系人已经存在，会返回异常
     */
    public boolean addPerson(Contact_Message person) throws Exception {
        String name = person.getFullName();
        ArrayList<Contact_Message> data;
        if (personBase.containsKey(name))
        {
            data = personBase.get(name);
            if (data.contains(person))
            {
                throw new Exception("该联系人已经存在，请不要重复添加");
            }
        }
        else
        {
            personBase.put(name, new ArrayList<>());
        }
            personBase.get(name).add(person);
            //将该人添加到其对应的分组里
            for(String groupName:person.getGroup())
            {   //如果存在该分组，会把该人添加到对应的分组
                if(hasGroup(groupName))
                {
                    addPersonToGroup(person,groupName);
                }
                else
                {
                    //如果不存在该分组，则新增分组，然后进行添加
                    addGroup(groupName);
                    if(!addPersonToGroup(person,groupName))
                    {   //如果再次添加失败则抛出异常
                        throw new Exception("添加联系人"+person.getFullName()+"到分组"+groupName+"失败");
                    }
                }
            }
            return true;
        }



    /**
     * 删除联系人以及相关数据（相片）
     *
     * @param person 联系人对象
     * @return
     */
    public boolean removePerson(Contact_Message person) {
        String name = person.getFullName();
        ArrayList<String> group = new ArrayList<>(person.getGroup());
        removePersonImage(person);
        if (personBase.containsKey(name)) {
            personBase.get(name).remove(person);
        }
        for(String groupName:group) {
            if (groupData.containsKey(groupName)) {
                groupData.get(groupName).removePerson(person);
            }
        }
        return true;
    }

    /**
     * 删除分组
     * @param groupName 分组名字
     * @throws Exception
     */
    public void removeGroup(String groupName) throws Exception
    {
        if(hasGroup(groupName))
        {   //对联系人中的分组进行删除操作
            for(Contact_Message person:getGroup(groupName).getGroup())
            {
                person.removeGroup(groupName);
            }
            groupData.remove(groupName);
        }
        else
        {
            throw new Exception("不存在该小组");
        }
    }

    /**
     * 删除联系人的头像文件
     * @param person 联系人对象
     */
    public void removePersonImage(Contact_Message person) {
        if (person.getPicture() == null){return ;}
        //获得头像的路径
        String imagePath=person.getPicture().getPath();
        //System.out.println(imagePath);
        if(imagePath.length()==0)
            return;
        //如果头像是在userFile的就执行删除
        if(imagePath.contains(getUserPath())) {
            (new File(imagePath)).delete();
        }
    }
    public ArrayList<Contact_Message> matchPingYing(String query)
    {
        query=query.toLowerCase();
        ArrayList<Contact_Message> result=new ArrayList<>();
        for(ArrayList<Contact_Message>people:personBase.values())
        {
            for(Contact_Message person:people)
            {
                String name=person.getFullName();
                String nameFirstSpell= PingYingUtil.getFirstSpell(name);
                String namePingYing=PingYingUtil.getFullSpell(name);
                if(nameFirstSpell.contains(query)||namePingYing.contains(query))
                {
                    result.add(person);
                }
            }
        }
        return result;
    }
    /**
     * 从联系人列表(personBase)中根据query返回搜索结果
     * @param query 查询关键词
     * @return 返回包含符合要求的Contact_Message的对象数组
     */
    public ArrayList<Contact_Message> search(String query)
    {
        //result 存放搜索结果
        ArrayList<Contact_Message> result = matchPingYing(query);
        SearchUtil.search(query,getPersonBase(),SearchUtil.getAllSearchRange(new Contact_Message()),result);
        return result;
    }

    /**
     * 从联系人列表(personBase)中根据query和搜索范围返回搜索结果
     * @param query 查询关键词
     * @param searchRange 搜索范围
     * @return  返回搜索结果
     */
    public ArrayList<Contact_Message> search(String query,ArrayList<String>searchRange)
    {
        //result 存放搜索结果
        ArrayList<Contact_Message> result = matchPingYing(query);
        SearchUtil.search(query,getPersonBase(),searchRange,result);
        return result;
    }

    /**
     * 获得全部联系人
     * @return Contact_Message的对象数组
     */
    public ArrayList<Contact_Message> getPersonBase()
    {
        ArrayList<Contact_Message> result=new ArrayList<>();
        for(ArrayList<Contact_Message> people:personBase.values())
        {
            for(Contact_Message person:people)
            {
                result.add(person);
            }
        }
        result.sort(new Comparator<Contact_Message>() {
            @Override
            public int compare(Contact_Message o1, Contact_Message o2) {
                return PingYingUtil.getFullSpell(o1.getFullName()).compareTo(PingYingUtil.getFullSpell(o2.getFullName()));
            }
        });
        return result;
    }

    /**
     * get未分组的联系人列表
     * @return 未分组的联系人列表
     */
    public ArrayList<Contact_Message> getPersonBaseWithNoGroup()
    {
        ArrayList<Contact_Message> result=new ArrayList<>();
        for(Contact_Message person:getPersonBase())
        {
            if(person.isEmptyGroup())
            {
                result.add(person);
            }
        }
        result.sort(new Comparator<Contact_Message>() {
            @Override
            public int compare(Contact_Message o1, Contact_Message o2) {
                return PingYingUtil.getFullSpell(o1.getFullName()).compareTo(PingYingUtil.getFullSpell(o2.getFullName()));
            }
        });
        return result;
    }
    /**
     * 根据组名获得分组的对象
     * @param name 组名
     * @return 返回分组的对象
     * @throws Exception 当分组不存在时会返回异常
     */
    public Contact_Group getGroup(String name) throws Exception
    {
        if(!groupData.containsKey(name))
        {
            throw  new Exception(name + "分组不存在");
        }
        else
        {
            return groupData.get(name);
        }
    }

    /**
     * 获得星标好友列表
     * @return
     */
    public ArrayList<Contact_Message> getStarList()
    {
        ArrayList<Contact_Message>result=new ArrayList<>();
        for(Contact_Message person:getPersonBase())
        {
            if(person.getIsStart())
            {
                result.add(person);
            }
        }
        return result;
    }

    public String getUsername() {
        return username;
    }

    /**
     * get联系人总数
     * @return 联系人总数
     */
    public int getContactNumber(){
        int number = 0;
        for(Map.Entry<String, ArrayList<Contact_Message>> entry : personBase.entrySet()){
            number += ((ArrayList)entry.getValue()).size();
        }
        return number;
    }

    /**
     * get星标联系人数量
     * @return 星标联系人数量
     */
    public int getStarNumber(){
        return getStarList().size();
    }

    /**
     * 根据名字添加分组
     * @param name 分组名字
     * @throws Exception 如果分组已经存在会丢出异常
     */
    public void addGroup(String name) throws Exception
    {
        if(hasGroup(name))
        {
            throw new Exception("该分组已经存在");
        }
        else
        {
            groupData.put(name,new Contact_Group(username,name));
        }
    }

    public void addGroup(String name,Contact_Group group) throws Exception
    {
        if(hasGroup(name))
        {
            throw new Exception("该分组已经存在");
        }
        else
        {
            groupData.put(name,group);
        }
    }

    /**
     * 根据组名判断是否已经存在该分组
     * @param name 组名
     * @return 如果存在返回true，否则返回false
     */
    public boolean hasGroup(String name)
    {
        return groupData.containsKey(name);
    }

    /**
     * 修改组名以及小组成员对应分组名
     * @param oldName 旧组名
     * @param newName 新组名
     * @throws Exception
     */
    public void modifyGroupName(String oldName,String newName) throws Exception {
        if (groupData.containsKey(oldName)) {
            Contact_Group group = groupData.get(oldName);
            group.setGroupName(newName);
              //该函数应该只需实现修改组名的功能
//            groupData.remove(oldName);
//            groupData.put(newName,group);
        }
        else
            throw new Exception("there is no Group called" + oldName);
    }

    /**
     * 添加联系人到对应的分组
     * @param person 联系人对象
     * @param group  分组名
     * @return 如果添加成功返回true，否则返回false
     */
    public boolean addPersonToGroup(Contact_Message person,String group) throws Exception
    {   //判断分组是否存在
        if(hasGroup(group))
        {   //判断person对象有没有小组信息
            if(!person.hasGroup(group))
            {
                person.addGroup(group);
            }
            //判断person对象是否已经存在于目标分组中
            if(getGroup(group).getGroup().contains(person))
            {
                throw new Exception(person.getFullName()+"成员已经在分组中");
            }

            getGroup(group).addMember(person);
            return true;
        }
        else
        {
            throw new Exception("不存在该分组");
        }
    }

    /**
     * 获取所有分组的名称的列表
     * @return 所有分组的名称的列表
     */
    public ArrayList<String> getGroupNameList()
    {
        ArrayList<String> result=new ArrayList<>(groupData.keySet());
        result.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        return result;
    }

    /**
     *更新联系人的信息
     * @param preData 要更新的数据
     * @param newData 新的数据
     * @return 更新成功会返回true
     * @throws Exception 失败会返回异常，一般是没有设置getter和setter方法
     */
    public boolean update(Contact_Message preData,Contact_Message newData) throws Exception
    {
        try{
            //这样可以在不改变引用的情况下更新对象的属性
            CopyUtil.getBean(preData,newData);
            preData.setGroup(newData.getGroup());
            preData.setPhoneNumber(newData.getPhoneNumberList());
            preData.setEmail(newData.getEmailList());
            return true;
        }
        catch (Exception e) {
            throw e;
        }
    }

    /**
     * 保存函数，保存对象
     */
    public void save() throws IOException
    {
        UserData item=this;
        //判断路径是否存在
        String basePath=System.getProperty("user.dir")+"/userFile/"+this.username;
        if(!(new File(basePath)).exists())
        {   //如果路径不存在的话就创建文件夹
            //data文件夹用于存储用户的数据
            //image文件夹用于存储用户的图片信息
            (new File(basePath+"/data")).mkdirs();
            (new File(basePath+"/image")).mkdirs();
        }
        String dataPath=basePath+"/data/"+username+".dat";
        ObjectOutputStream output =new ObjectOutputStream(new FileOutputStream(dataPath));
        output.writeObject(item);
    }

    public void shiftPersonToGroup(Contact_Message person,String fromGroup,String toGroup) throws Exception
    {
        if(!hasGroup(fromGroup))
        {
            throw new Exception("当前分组不存在");
        }
        if(!hasGroup(toGroup))
        {
            throw new Exception("要移动的分组不存在");
        }
        if(person.hasGroup(toGroup))
        {
            throw new Exception(person.getFullName()+"已经在"+toGroup+"内");
        }
        else
        {
            addPersonToGroup(person,toGroup);
            getGroup(fromGroup).removePerson(person);
        }
    }


    public String getDataPath()
    {
        return System.getProperty("user.dir")+"/userFile/"+this.username+"/data/"+username+".dat";
    }

    public String getUserPath()
    {
        return System.getProperty("user.dir")+"/userFile/"+this.username+"/";
    }

    //以下关于用户配置

    /**
     * 获取配置路径
     * @return 配置路径
     */
    public String getConflictPath()
    {
        return getUserPath()+"data/"+username+".properties";
    }
    public boolean existConflictFile()
    {
        return (new File(getConflictPath())).exists();
    }
    /**
     * 创建配置文件
     */
    public void createUserConflict()
    {
        if(!new File(getUserPath()+"data").exists())
        {
            new File(getUserPath()+"data").mkdirs();
        }
        try {
            (new File(getConflictPath())).createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据key获取对应配置（为了安全地调用，如果key不存在会返回空字符串）
     * @param key key
     * @return 返回key对应的配置，若key不存在则返回空字符串""
     */
    public String getConflict(String key)
    {
        if(!existConflictFile())
        {
            createUserConflict();
        }
        Properties pps = new Properties();
        try {
            pps.load(new FileInputStream(getConflictPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        String res=pps.getProperty(key);
        if(res==null)
        {
            res="";
        }
        return res;
    }

    /**
     * 判断配置文件是否存在某配置
     * @param key key
     * @return 如果存在配置key则返回true，否则返回false
     */
    public boolean existConflict(String key)
    {
        if(!existConflictFile())
        {
            createUserConflict();
        }
        Properties pps = new Properties();
        try {
            pps.load(new FileInputStream(getConflictPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        String res=pps.getProperty(key);
        return (res != null);
    }

    /**
     * 设置并且保存配置（如果key已经存在，原value会被新value覆盖）
     * @param key key
     * @param value value
     */
    public void setAndSaveConflict(String key,String value)
    {
        if(!existConflictFile())
        {
            createUserConflict();
        }
        String ConflictPath=getConflictPath();
        Properties pps = new Properties();
        try {
            pps.load(new FileInputStream(ConflictPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        pps.put(key,value);
        OutputStream out = null;
        try {
            out = new FileOutputStream(ConflictPath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            if (out != null) {
                pps.store(out, "Update " + key + " name");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString() {
        return username+"的分组和所有联系人信息";
    }

}
